#include<iostream>
#include<pthread.h>
#include<mutex>
#include<queue>
using namespace std;


const int default_task_queue_cap = 5;
const int default_thread_cap = 3;

template<class T>
class ThreadPool
{
public:
  ThreadPool(int task = default_task_queue_cap,int thread = default_thread_cap)
    :_Taskcap(task),_Threadcap(thread)
  {
    pthread_mutex_init(&_mtx,nullptr);
    pthread_cond_init(&_empty,nullptr);
    pthread_cond_init(&_full,nullptr);
    InitThreadPool();
  }
  ~ThreadPool()
  {
    pthread_mutex_destroy(&_mtx);
    pthread_cond_destroy(&_empty);
    pthread_cond_destroy(&_full);
    _Taskcap = _Threadcap = 0;
  }
  
  void push(const T& task)
  {
    Lock();
    while(_task_queue.size() >= _Taskcap)
    {
      cout <<"任务队列满了" << endl;
      pthread_cond_wait(&_full,&_mtx);
    }
    _task_queue.push(task); 
    pthread_cond_signal(&_empty);
    UnLock();
  }

  
  void pop(T* task)
  {
    *task = _task_queue.front();
    _task_queue.pop();
  }

  bool empty() const 
  {
    return _task_queue.empty();
  }

  static void* Routine(void* arg)
  {
    pthread_detach(pthread_self());
    ThreadPool<T>* tp = static_cast<ThreadPool<T>*>(arg);
    while(1)
    {
      tp->Lock(); 
      while(tp->empty()) //任务队列为空
      {
        cout <<"任务队列为空" <<" " <<pthread_self() <<"进入等待"<<endl;
        pthread_cond_wait(&tp->_empty,&tp->_mtx);
      }
      T task;
      tp->pop(&task);
      tp->UnLock();
      pthread_cond_signal(&tp->_full);
      task(); //task.operator() 
    }
  }

  void InitThreadPool()
  {
    cout <<"===================" << endl;
    for(int i = 0;i<_Threadcap;i++)
    {
      pthread_t tid;
      pthread_create(&tid,nullptr,Routine,this);
    }
    cout <<"===================" << endl;
  }
  void Lock() 
  {
    pthread_mutex_lock(&_mtx);
  } 
  void UnLock()
  {
    pthread_mutex_unlock(&_mtx);
  }

private:
  queue<T> _task_queue;
  pthread_mutex_t _mtx;
  pthread_cond_t _empty;
  pthread_cond_t _full;
  int _Taskcap;
  int _Threadcap;
};
